<template>
    <div class="mescroll" ref="element" :id="elementId">
        <div class="scroll-view-content" ref="content">
            <slot></slot>
        </div>
    </div>
</template>

<script lang="ts">
    import Vue from 'vue';
    import {
        Prop,
        Emit,
        Component,
    } from 'vue-property-decorator';

    import meScroll from 'mescroll.js';
    import "mescroll.js/mescroll.min.css";

    import {
        ScrollViewUp
    } from './index'

    @Component
    export default class ScrollView extends Vue {
        scrollY: number = 0;
        myScroll: any = null;
        refreshEndTimer: any = null;
        meScroll: any = meScroll as any;
        @Prop({default: 0}) readonly page!: number;
        @Prop({default: () => ({})}) value!: object;
        @Prop({default: 15}) readonly pageSize!: number;
        @Prop({default: true}) readonly useRefresh!: boolean;
        @Prop({default: true}) readonly useLoadMore!: boolean

        mounted() {
            this.init();
        }

        private init() {
            const {
                element
            } = this.$refs;

            this.myScroll = (
                new this.meScroll(
                    element,
                    this.options
                )
            )
        }

        private get elementId() {
            return `scroll-view-${Date.now()}`
        }

        private get options(): object {
            const {
                content
            } = this.$refs;

            return {
                down: {
                    auto: false,
                    use: this.useRefresh,
                    callback: () => this.onRefresh()
                },
                up: {
                    empty: {
                        warpId: content
                    },
                    page: {
                        num: this.page,
                        size: this.pageSize
                    },
                    use: this.useLoadMore,
                    noMoreSize: this.pageSize,
                    onScroll: (e: any) => this.onScroll(e),
                    callback: (page: ScrollViewUp) => this.onLoadMore(page)
                }
            }
        }

        private onRefresh(): void {
            this.onRefreshEmit();
        }

        private onLoadMore(page: ScrollViewUp): void {
            this.onLoadMoreEmit(
                page, (len: number) => this.onLoadMoreEnd(len)
            );
        }

        @Emit(`onRefresh`)
        private onRefreshEmit(): Function {
            return () => this.onRefreshEnd()
        }

        @Emit(`onLoadMore`)
        private onLoadMoreEmit(page: ScrollViewUp, cb: Function): void {}

        @Emit(`scroll`)
        private onScroll(e: any) {
            this.scrollY = this.getScrollTop();
            return this.scrollY;
        }

        private onRefreshEnd() {
            this.refreshEndTimer = (
                setTimeout(() => {
                    this.myScroll.endSuccess()
                }, 500)
            )
        }

        private onLoadMoreEnd(length: number): void {
            const hasNext: boolean = length >= this.pageSize;
            this.$nextTick(() => {
                this.myScroll.endSuccess(length, hasNext)
            })
        }

        private clearTimer() {
            [this.refreshEndTimer].filter(v => !!v).forEach(t => clearTimeout(t))
        }

        private getScrollTop():number {
            return this.myScroll.getScrollTop()
        }

        beforeDestroy() {
            this.clearTimer();
            this.myScroll.destroy();
        }

        activated() {
            this.myScroll.scrollTo(this.scrollY, 0);
        }

        deactivated(){
            this.scrollY = this.getScrollTop();
        }
    }

</script>

<style scoped lang="scss">
    .scroll-view-content {
        overflow: hidden;
        min-height: calc(50% - 48px);
    }
</style>